﻿using CommonBehaviors.Actions;
using Styx;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media;


using disc = Paster.Disc.Rotation;
using shadow = Paster.Shadow.Rotations;
using spells = Paster.Spell.Spells;
using units = Paster.Managers.Units;
using movement = Paster.Managers.Movement;
using groups = Paster.Managers.Groups;
using EH = Paster.Managers.EventHandlers;
using CL = Paster.Managers.CombatLogEventArgs;

using CS = Paster.GUI.CommonSettings;
using DS = Paster.GUI.DiscSettings;
using Movement = Paster.Managers.Movement;
using HKM = Paster.Managers.HotkeyManagers;

using Styx.WoWInternals;
using Styx.CommonBot;
using System.Diagnostics;
using Styx.Pathing;

namespace Paster
{
    public class Main : CombatRoutine
    {
        public override string Name { get { return "Disc Priest Routine by Pasterke"; } }
        public override WoWClass Class { get { return WoWClass.Priest; } }
        public static LocalPlayer Me { get { return StyxWoW.Me; } }

        public override Composite CombatBehavior { get { return new ActionRunCoroutine(ctx => rotationSelector()); } }
        public override Composite PreCombatBuffBehavior { get { return new ActionRunCoroutine(ctx => PreCombatBuffCoroutine()); } }
        public override Composite PullBuffBehavior { get { return new ActionRunCoroutine(ctx => PullCoroutine()); } }

        public override bool WantButton { get { return true; } }
        public override void OnButtonPress()
        {
            new Paster.GUI.Form1().ShowDialog();
        }

        public static bool _init = false;
        public override void Initialize()
        {
            Lua.Events.AttachEvent("GLYPH_ADDED", UpdateMyGlyphEvent);
            HKM.registerHotKeys();
            UpdateMyGlyph();
            _init = true;

        }
        public override void ShutDown()
        {
            HKM.removeHotkeys();
            Lua.Events.DetachEvent("GLYPH_ADDED", UpdateMyGlyphEvent);
        }

        public static int LastPartySize = 0;
        public static DateTime _fpsTimer;

        public override void Pulse()
        {
            try
            {
                if (Me.IsDead
                    && units.AutoBot)
                {
                    Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                }
                checkGroup();
            }
            catch { }
            return;
        }
        public static void checkGroup()
        {
            if (LastPartySize != groups.partyCount) 
            {
                Logging.Write(Colors.CornflowerBlue, "Old Party Size: " + LastPartySize + " New Party Size: " + groups.partyCount);

                LastPartySize = groups.partyCount;
                _init = true; 
            }
        }

        public static async Task<bool> rotationSelector()
        {
            if (Me.Specialization == WoWSpec.PriestDiscipline && await disc.DiscRoutine()) return true;
            if (Me.Specialization == WoWSpec.PriestShadow && await shadow.ClarityOfPowerRoutine()) return true;
            return false;
        }
        private static async Task<bool> PreCombatBuffCoroutine()
        {
            if (await spells.CastBuff(spells.PowerWordFortitude, CS.myPrefs.fortitude != CS.powerwordfortitude.Manual
                && !Me.HasAura(spells.PowerWordFortitude), Me)) return true;
            if (await spells.CastBuff(spells.PowerWordShield, !units.buffExists(spells.PowerWordShield, Me) 
                && Me.IsMoving 
                && units.Canbuff
                && SpellManager.HasSpell("Body and Soul"), Me)) return true;
            return false;
        }

        public override bool NeedRest
        {
            get
            {
                if (Me.HasAura("Food") || Me.HasAura("Drink")) return false;
                if (Me.HealthPercent <= CS.myPrefs.EatFood && !Me.IsSwimming && units.Canbuff) return true;
                if (Me.ManaPercent <= CS.myPrefs.DrinkMana && !Me.IsSwimming && units.Canbuff) return true;
                if (Me.HealthPercent <= CS.myPrefs.FlashHealOOC && SpellManager.HasSpell(spells.FlashHeal) && units.Canbuff) return true;
                return false;
            }
        }
        public override void Rest()
        {
            
            if (Me.HealthPercent <= CS.myPrefs.EatFood && !Me.IsSwimming && units.Canbuff) { Styx.CommonBot.Rest.Feed(); }
            if (Me.ManaPercent <= CS.myPrefs.DrinkMana && !Me.IsSwimming && units.Canbuff) { Styx.CommonBot.Rest.Feed(); }
            if (Me.HealthPercent <= CS.myPrefs.FlashHealOOC && !Me.HasAura("Food") && !Me.HasAura("Drink") && SpellManager.HasSpell(spells.FlashHeal) && units.Canbuff)
            {
                SpellManager.Cast(spells.FlashHeal, Me);
            }
            base.Rest();
        }


        public static WoWGuid lastGuid;
        public static Stopwatch pullTimer = new Stopwatch();
        public static Stopwatch fightTimer = new Stopwatch();
        public static int dpsDist
        {
            get
            {
                if (Me.Specialization == WoWSpec.PriestShadow) { return 35; }
                if (HasGlyphName.Contains("Holy Fire")) { return 35; }
                return 25;
            }
        }

        private static async Task<bool> PullCoroutine()
        {
            if (Me.IsCasting) return false;
            if (!pullTimer.IsRunning && units.AutoBot)
            {
                pullTimer.Restart();
                lastGuid = Me.CurrentTarget.Guid;
                Logging.Write(Colors.CornflowerBlue, "Starting PullTimer");
            }
            if (await units.CannotPull(Me.CurrentTarget, Me.CurrentTarget != null
                && pullTimer.ElapsedMilliseconds >= 30 * 1000
                && lastGuid == Me.CurrentTarget.Guid)) return true;

            if (CS.myPrefs.AutoMovement) await Movement.MoveToCombatTarget();
            if (CS.myPrefs.AutoFacing) await Movement.FaceMyCurrentTarget();
            
            if (await spells.Cast(spells.HolyFire, Me.CurrentTarget != null 
                && Me.Specialization == WoWSpec.PriestDiscipline, Me.CurrentTarget)) return true;
            if (await spells.Cast(spells.PowerWordSolace, Me.CurrentTarget != null 
                && Me.Specialization == WoWSpec.PriestDiscipline, Me.CurrentTarget)) return true;
            if (await spells.Cast(spells.MindFlay, Me.CurrentTarget != null 
                && Me.Specialization == WoWSpec.PriestShadow 
                && Me.Level >= 10, Me.CurrentTarget)) return true;
            if (await spells.Cast(spells.Smite, Me.CurrentTarget != null
                && (Me.Specialization == WoWSpec.PriestDiscipline
                || Me.Specialization == WoWSpec.PriestHoly
                || (Me.Specialization == WoWSpec.PriestShadow && Me.Level < 10)), Me.CurrentTarget)) return true;


            return false;
        }

        

        #region UpdateMyGlyph

        private static void UpdateMyGlyphEvent(object sender, LuaEventArgs args)
        {
            UpdateMyGlyph();
        }


        public static string HasGlyph;
        public static string HasGlyphName;

        private static void UpdateMyGlyph()
        {
            HasGlyph = "";
            HasGlyphName = "";
            {
                var glyphCount = Lua.GetReturnVal<int>("return GetNumGlyphSockets()", 0);

                if (glyphCount != 0)
                {
                    for (int i = 1; i <= glyphCount; i++)
                    {
                        string lua =
                            String.Format(
                                "local enabled, glyphType, glyphTooltipIndex, glyphSpellID, icon = GetGlyphSocketInfo({0});if (enabled) then return glyphSpellID else return 0 end",
                                i);

                        var glyphSpellId = Lua.GetReturnVal<int>(lua, 0);

                        try
                        {
                            if (glyphSpellId > 0)
                            {
                                HasGlyphName = HasGlyphName + "[" + (WoWSpell.FromId(glyphSpellId)) + " - " +
                                               glyphSpellId +
                                               "] " + "\r\n";
                                HasGlyph = HasGlyph + "[" + glyphSpellId + "] ";
                            }
                        }
                        catch (Exception ex)
                        {
                            Logging.Write("Report this message to us: " + ex);
                        }
                    }
                }

                Logging.Write(Colors.SeaShell,"----------------------------------");
                Logging.Write(Colors.SeaShell, "Glyphs:" + "\r\n");
                Logging.Write(Colors.SeaShell, HasGlyphName);
                Logging.Write(Colors.SeaShell, "----------------------------------");
            }
        }

        #endregion
    }
}
